﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using SdmxMl.Common;
using System.Windows.Forms;
using SdmxMl.Helper;

namespace SdmxMl.Structure
{
    public class NestedHierarchicalList : List<ISdmxHierarchyListItem>, IHierarchyManage
    {
        protected NestedHierarchicalList rootHierarchy;
        public bool HasHierarchy
        {
            get { return true; }
            set { ; }
        }

        public NestedHierarchicalList Root
        {
            get { return rootHierarchy; }
        }

        public NestedHierarchicalList(NestedHierarchicalList root)
        {
            rootHierarchy = (root == null) ? this : root;
        }

        #region IHierarchyManage Members

        public bool RemoveHierarchicalItem(ISdmxHierarchyListItem it)
        {
            bool deleted = false;
            foreach (ISdmxHierarchyListItem item in this)
            {
                if (item == it)
                {
                    this.Remove(item);
                    deleted = true;
                    break;
                }
                if (item.InnerHierarchy.RemoveHierarchicalItem(it) == true)
                {
                    deleted = true;
                    break;
                }
            }
            return deleted;
        }

        /// <summary> Checks if code already used and if Yes, create a unique code for proposed item.</summary>
        /// <param name="it">the proposed item</param>
        /// <returns>True if parameter item Id already used by other item in the list</returns>
        private bool CreateUniqueCode(ISdmxHierarchyListItem it, NestedHierarchicalList nhl)
        {
            // Checks On specified level only
            Dictionary<string, string> h = new Dictionary<string, string>();

            foreach (ISdmxHierarchyListItem item in nhl)
                if (it != item)
                    if (h.ContainsKey(item.Id) == false)
                        h.Add(item.Id, item.Id);

            int nb = 1;
            bool alreadyDefined = false;
            while (h.ContainsKey(it.Id))
            {
                alreadyDefined = true;
                it.Id = "undefined" + nb.ToString();
                nb++;
            }
            return alreadyDefined;
        }


        /// <summary>Rename proposed item and all its childs references</summary>
        /// <param name="it">the proposed item</param>
        public bool RenameHierarchicalItem(ISdmxHierarchyListItem it, string newName)
        {
            string oldName = it.Id;
            it.Id = newName;
            bool ret = CreateUniqueCode(it, this);
            return ret;
        }

        public TreeNode NewChild(System.Windows.Forms.TreeNode node)
        {
            NestedHierarchicalList nh = rootHierarchy;
            TreeNode t = node;
            if (node != null)
            {
                ISdmxHierarchyListItem parentItem = node.Tag as ISdmxHierarchyListItem;
                if (parentItem != null) // not in root
                    nh = parentItem.InnerHierarchy as NestedHierarchicalList;
                
                ISdmxHierarchyListItem item = nh.CreateNewItem(parentItem);
                CreateUniqueCode(item, nh);
                if (nh != null)
                    nh.Add(item);

                BaseArtefact ba = item as BaseArtefact;
                t = ba.FillNode(node);
            }
            return t;
        }
        //(To be redefined in derived class
        public virtual ISdmxHierarchyListItem GetParent(ISdmxHierarchyListItem it)
        {
            return null;
        }

        public virtual void RedefineParent(ISdmxHierarchyListItem item, string newParentId, object newOwner)
        {
        }


        #endregion


        public virtual ISdmxHierarchyListItem CreateNewItem(ISdmxHierarchyListItem parentItem)
        {
            return null;
        }

        /// <summary>Provides list of possible parents for suggested item</summary>
        /// <param name="item">Suggested item</param>
        /// <returns>the list as a table with id and description name</returns>
        public DataTable PossibleParentsDataTable(ISdmxHierarchyListItem item)
        {
            DataTable dataTable = CreateTableContainer();
            FillPossibleParent(null, dataTable, item);
            return dataTable;
        }

        protected virtual void FillPossibleParent(NestedHierarchicalList cur, DataTable dataTable, ISdmxHierarchyListItem item)
        {
            NestedHierarchicalList nhl = cur == null ? rootHierarchy : cur;
            foreach (ISdmxHierarchyListItem it in nhl)
            {
                if (item != it)
                {
                    dataTable.Rows.Add(new object[] { it.Id, it.Name, it });
                    FillPossibleParent((it.InnerHierarchy as NestedHierarchicalList), dataTable, item);
                }
            }
       }

        public DataTable GetTableRepresentation()
        {
            DataTable dataTable = CreateTableContainer();
            FillTableRepresentation(null, dataTable);
            return dataTable;
        }

        protected virtual void FillTableRepresentation(NestedHierarchicalList cur, DataTable dataTable)
        {
            NestedHierarchicalList nhl = cur == null ? rootHierarchy : cur;
            foreach (ISdmxHierarchyListItem it in nhl)
            {
                    dataTable.Rows.Add(new object[] { it.Id, it.Name });
                    FillTableRepresentation((it.InnerHierarchy as NestedHierarchicalList), dataTable);
            }
        }


        /// <summary>Create table container object</summary>
        /// <returns>The dataTable object</returns>
        private DataTable CreateTableContainer()
        {
            DataTable dataTable = new DataTable();
            dataTable.Columns.Add(new DataColumn("Code", typeof(string)));
            dataTable.Columns.Add(new DataColumn("Description", typeof(string)));
            dataTable.Columns.Add(new DataColumn("Object", typeof(object)));

            return dataTable;
        }
        
        /// <summary>Creates flat or hierarchical hierarchy</summary>
        /// <param name="parentNode"></param> <returns></returns>
        public virtual TreeNode FillTree(TreeNode parentNode)
        {
            foreach (ISdmxHierarchyListItem it in rootHierarchy)
                it.FillNode(parentNode);
            return parentNode;
        }


    }
}
